﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using MDT.LifeSewagePlatform.InterfaceService;
using MDT.LifeSewagePlatform.Entity;
using MDT.LifeSewagePlatform.Conmmon;
using Microsoft.EntityFrameworkCore;
using MDT.LifeSewagePlatform.IRepository;
using AutoMapper;
using Microsoft.Extensions.Configuration;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.Extensions.Logging;

namespace MDT.LifeSewagePlatform.Service
{
    public class UserService : BaseService, IUserService
    {

        #region
        [Autowired]
        private IUserRepository userRepository { get; set; }
        [Autowired]
        private IMapper mapper { get; set; }
        [Autowired]
        private ISendEmail sendEmail { get; set; }
        [Autowired]
        private IConfiguration configuration { get; set; }

        [Autowired]
        protected ICacheTokenDictionary CacheTokenDictionary { get; set; }
        public UserService()
        {
        }
        #endregion
        public async Task<BaseMessage> Login(LoginModel model)
        {
            
            #region Params verify 
            var verifyResualt = model.Verify();
            if (verifyResualt.Item2 == false)
            {
                return BadRequest400(verifyResualt.Item1);
            }
            #endregion

            IQueryable<UserView> users = userRepository.GetUsers(u => u.Phone.Trim() == model.Account.Trim());
            if (await users.AnyAsync())
            {
                UserView User = await users.FirstOrDefaultAsync();


                if (User != null && User.UserPassword == MD5Encrypt.Encrypt(model.UserPassword))
                {
                    string token = await GetToken(User);
                    CacheTokenDictionary.AddToken(User.ID,token);
                    return Ok200("登录成功!", token);
                }
            }
            return BadRequest400("登录失败!");
        }


        public async Task<BaseMessage> Add(AddUser user, int ID)
        {

            #region Params verify 
            var verifyResualt = user.Verify();
            if (verifyResualt.Item2 == false)
            {
                return BadRequest400(verifyResualt.Item1);
            }

            if (user.RoleID == (int)eRoleType.Admin)
            {
                return BadRequest400("系统不允许添加管理员!");
            }

            if ((int)eRoleType.GeneralChild == user.RoleID)
            {
                if (user.CurrentAreaID <= 0)
                {
                    return BadRequest400("请为子用户，绑定其可以查看的区域!");
                }
            }
            if ((await userRepository.AnyAsync(u => u.PhoneNumber == user.PhoneNumber)))
            {
                return BadRequest400("更新失败,手机号已存在!");
            }

            #endregion
            UserEntity userEntity = mapper.Map<UserEntity>(user);
            userEntity.UserPassword = MD5Encrypt.Encrypt(userEntity.UserPassword);
            await userRepository.Create(userEntity, ID);
            if (await userRepository.SaveChangesAsync())
            {
                return Ok200("添加成功!");
            }
            return BadRequest400("添加失败!");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="user">更新的信息</param>
        /// <param name="UserID">更新人ID</param>
        /// <param name="ID">操作的管理员</param>
        /// <returns></returns>
        public async Task<BaseMessage> Update(UpdateUser user, int ID, int UserID)
        {


            UserEntity userEntity = await userRepository.FirstOrDefaultAsync(u => u.ID == ID);
            if (string.IsNullOrEmpty(user.UserPassword))
            {
                user.UserPassword = userEntity.UserPassword;
            }
            else
            {
                user.UserPassword = MD5Encrypt.Encrypt(user.UserPassword);
            }
            mapper.Map(user, userEntity);
            await userRepository.Update(userEntity, UserID);
            if(await userRepository.SaveChangesAsync())
            {
                return Ok200("更新成功!");
            }
            return BadRequest400("更新失败!");
        }

        public async Task<BaseMessage> UpdatePassword(int UserID, UpdatePassword updatePassword)
        {
            if (string.IsNullOrEmpty(updatePassword.NewPassword))
            {
                return BadRequest400("输入密码不能为空!");
            }
            if (updatePassword.NewPassword != updatePassword.RePassword)
            {
                return BadRequest400("两次密码输入不一致!");
            }
            UserEntity userEntity = await userRepository.FirstOrDefaultAsync(u => u.ID == UserID);

            if (MD5Encrypt.Encrypt(updatePassword.OldPassword) != userEntity.UserPassword)
            {
                return BadRequest400("密码错误!");
            }
            userEntity.UserPassword = MD5Encrypt.Encrypt(updatePassword.NewPassword);
            var entity = await userRepository.Update(userEntity, UserID);
            if( await userRepository.SaveChangesAsync())
            {
                return Ok200("更新成功!");
            }
            return BadRequest400("更新失败!");
        }

        public async Task<BaseMessage> GetUsers(UserParameter Params)
        {
            IQueryable<UserView> users = userRepository.GetUsers(t => true);
            return Ok200("查询成功!",await PageList<UserView>.CreateAsync(users, Params));
        }

        public async Task<BaseMessage> FindUserById(int ID)
        {
            return Ok200("查询成功!",await userRepository.GetUsers(u => u.ID == ID).FirstOrDefaultAsync());
        }

        public async Task<BaseMessage> SoftDelete(int ID, int UserID)
        {
            await userRepository.SoftDelete(u => u.ID == ID, UserID);
            if (await userRepository.SaveChangesAsync())
            {
                return Ok200("删除成功!");
            }
            return BadRequest400("删除失败!");
        }

        public async Task<BaseMessage> UnSoftDelete(int ID, int UserID)
        {
            UserEntity entity = await userRepository.FirstOrDefaultAsync(u => u.ID == ID);
            entity.IsDelete = false;
            var model = await userRepository.Update(entity, UserID);
            bool IsOk = await userRepository.SaveChangesAsync();
            if (IsOk)
            {
                return Ok200("还原成功!");
            }
            return BadRequest400("还原失败!");
        }

        public async Task<BaseMessage> GetCode(string phone)
        {
            UserEntity entity = await userRepository.FirstOrDefaultAsync(u => u.PhoneNumber == phone);

            if (entity == null)
            {
               return BadRequest400("电话号码不存在!");
            }
            EmailModel emailModel = configuration.GetSection("EmailConfig").Get<EmailModel>();
            entity.Email = 4.GetRandom();
            entity.CodePastTime = DateTime.Now.AddMinutes(5);

            string msg = $"尊敬的用户,你的验证码是:{entity.Email}请在五分钟内完成密码修改!";
            sendEmail.SendMessage(emailModel, entity.Email, msg);
            await userRepository.Update(entity, entity.ID);
            if(await userRepository.SaveChangesAsync())
            {
                return Ok200("验证码已发送,请注意查收!");
            }
            return BadRequest400("获取验证码失败!");
        }

        public async Task<BaseMessage> FrogetPassword(ForgetPassword Params)
        {
            if (Params.RePassword != Params.Password)
            {
                return BadRequest400("两次输入的密码不一致,请确保一致。");
            }

            UserEntity entity = await userRepository.FirstOrDefaultAsync(u => u.PhoneNumber == Params.PhoneNumber);
            if (entity == null)
            {
               return BadRequest400("电话号码不存在!");
            }
            if (entity.EmailCode == Params.Code && entity.CodePastTime >= DateTime.Now)
            {
                entity.UserPassword = MD5Encrypt.Encrypt(Params.Password);
                await userRepository.Update(entity, entity.ID);
                if (await userRepository.SaveChangesAsync())
                {
                    return Ok200("修改成功!");
                }
                return BadRequest400("修改失败!");
            }
            else
            {
               return BadRequest400("验证失败请重新尝试!");
            }
        }


        public async Task<BaseMessage> Delete(int id)
        {
            var query = from user in userRepository._dbContext.Users.AsNoTracking()
                        join role in userRepository._dbContext.Roles.AsNoTracking() on user.RoleID equals role.ID
                        where user.ID == id && role.RoleName == "Admin"
                        select user;
            if (await query.AnyAsync())
            {
               return BadRequest400("删除失败,管理员账号不能删除!");
            }
            await userRepository.Delete(t => t.ID == id);

            if (await userRepository.SaveChangesAsync())
            {
                return Ok200("删除成功!");
            }
            return BadRequest400("删除失败!");
        }

        protected async Task<string> GetToken(UserView user)
        {
            return await Task.Run<string>(() =>
            {
                var Config_TokenParameter = configuration.GetSection("JsonWebTokenConfiguration").Get<JsonWebTokenEntity>();

                var claims = new[]
                             {
                new Claim (ClaimTypes.NameIdentifier,user.ID.ToString()),
                new Claim (ClaimTypes.Role,user.RoleValue.ToString()),
                new Claim ("RoleName",user.RoleName),
                new Claim ("CompanyID",user.CompanyID.ToString()),
                new Claim ("PlaceTypeID",user.PlaceTypeID.ToString()),
                new Claim ("PlaceTypeName",user.PlaceTypeName),
                new Claim ("RoleID",user.RoleID.ToString()),
                new Claim ("CurrentAreaID",user.CurrentAreaId.ToString()),
             };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Config_TokenParameter.Secret));
                var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var jwtToken = new JwtSecurityToken(Config_TokenParameter.Issuer, Config_TokenParameter.Audience,
                    claims, expires: DateTime.UtcNow.AddMinutes(Config_TokenParameter.AccessExpiration), signingCredentials: credentials);
                var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
                return token;
            });
        }
    }
}